// data 中的数据 都是用 Object.defineProperty 重新定义 es5
// 所以 vue2 无法兼容 IE8 及以下版本
import { isObject,def } from '../util/index'
import {arrayMethods} from './array.js'
class Observer {
    constructor(value) {
        // vue 如果数据的层次过多，需要递归去解析对象中的属性，一次增加set和get方法
        // proxy
        // value.__ob__ = this; // 我给每个监控过的对象都增加一个 __ob__ 属性
        def(value,'__ob__',this);
        if (Array.isArray(value)){
            // 如果是数组的话并不会对索引进行观测，因为会导致性能问题
            // 因为前段开发中很少去操作索引 咱用的更多是 push shift unshitf
            value.__proto__ = arrayMethods;

            // 如果数组里放的是对象，我再监控
            this.observerArray(value);
        } else {
            this.walk(value)
        }
    }
    observerArray(value) {
        for (let i = 0; i < value.length; i++) {
            observe(value[i])
        }
    }
    walk(data) {
        let keys = Object.keys(data); // [name,age,address]

        keys.forEach((key) => {
            defineReactive(data, key, data[key]) //循环key依次添加响应式属性
        })
    }
}

function defineReactive(data, key, value) {
    observe(value) // 递归，对data中的对象进行响应式操作，递归实现深度检测
    Object.defineProperty(data, key, {
        get() { // 获取值的时候做一些操作
            console.log("获取数据")
            return value;
        },
        set(newValue) { // 也可以做一些操作
            console.log("更新数据")
            if (newValue == value) return;
            observe(newValue); //继续劫持用户设置的值，因为用户设置的值有可能是一个对象
            value = newValue;
        }
    })
}

export function observe(data) {
    let isObj = isObject(data);
    if (!isObj) {
        return;
    }
    return new Observer(data);

}